home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 October: Technology Seed / ADC Seed CD - October 1999.toast / FireWire / FireWire_2.0_SDK / Source / AVTransport / AVTransportFamily / AVTransportFamily.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-04-12  |  26.7 KB  |  1,088 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        AVTransportFamily.c
  3.  
  4.     Contains:    Services provided by the AV transport control driver family.
  5.  
  6.     Version:    1.0
  7.  
  8.     Written by:    Erik Staats
  9.  
  10.     Copyright:    © 1996-1998 by Apple Computer, Inc., all rights reserved.
  11.  
  12.     File Ownership:
  13.  
  14.         DRI:                Eric Anderson
  15.  
  16.         Other Contact:        
  17.  
  18.         Technology:            FireWire
  19.  
  20.     Writers:
  21.  
  22.         (jkl)    Jay Lloyd
  23.  
  24.     Change History (most recent first):
  25.  
  26.          <8>     1/15/98    jkl        Update for new headers.
  27.        <FW7>     3/18/97    ES        Changed to not create new AVT driver if we get device added
  28.                                     notification for a device we already have in our device list.
  29.        <FW6>      2/7/97    ES        Removed calls to AESendSystemEvent. Added equivalent
  30.                                     implementation. Added GetNextAVTClientEvent.
  31.        <FW5>    10/22/96    ES        Changed to use generic driver model. Changed to use Generic
  32.                                     Driver Family notification rather than DevNLib notification.
  33.        <FW4>      8/1/96    ES        Took out unused local variables.
  34.        <FW3>     6/27/96    ES        Took out include of AdminMessagePort.h.
  35.        <FW2>     6/20/96    ES        Filled in contains and written by fields.
  36.        <FW1>     6/20/96    ES        first checked in
  37.  
  38. */
  39.  
  40. #include <Types.h>
  41. #include <Errors.h>
  42. #include <Strings.h>
  43. #include <Traps.h>
  44. #include <Events.h>
  45. #include <Processes.h>
  46. #include <AppleEvents.h>
  47. #include <Devices.h>
  48. #include <CodeFragments.h>
  49. #include <DriverServices.h>
  50. #include <NameRegistry.h>
  51. #include <GenericDriverFamily.h>
  52. #include <AVTransport.h>
  53. #include <AVTransportPriv.h>
  54. #include <AVTransportExpert.h>
  55.  
  56. ////////////////////////////////////////////////////////////////////////////////
  57. //
  58. // Define global structure to hold all of the AV transport control driver
  59. // Family data.
  60. //
  61.  
  62. AVTFamilyDataPtr                gpAVTFamilyData = nil;
  63. AVTExpertDataPtr                gpAVTExpertData = nil;
  64.  
  65.  
  66. ////////////////////////////////////////////////////////////////////////////////
  67. //
  68. // Internal routine prototypes.
  69. //
  70.  
  71. static OSStatus    AVTEventHandler (
  72.     GDFDeviceEventDataPtr        pGDFDeviceEventData);
  73.  
  74. static OSStatus    AVTHandleDeviceAdded (
  75.     GDFDeviceEventDataPtr        pGDFDeviceEventData);
  76.  
  77. static OSStatus    AVTHandleDeviceRemoved (
  78.     GDFDeviceEventDataPtr        pGDFDeviceEventData);
  79.  
  80. static OSErr    AVTSendClientAppleEvent (
  81.     AVTClientDataPtr            pAVTClientData,
  82.     const AppleEvent            *theAppleEvent,
  83.     AESendMode                    sendMode,
  84.     AESendPriority                sendPriority,
  85.     long                        timeOutInTicks,
  86.     AEIdleUPP                    idleProc,
  87.     AEFilterUPP                    filterProc);
  88.  
  89. static void    DisposeClientAppleEventData (
  90.     ClientAppleEventDataPtr        pClientAppleEventData);
  91.  
  92. static OSStatus    AVTCreateClientAppleEventQueue (
  93.     AVTClientDataPtr            pAVTClientData);
  94.  
  95. static OSStatus    AVTDisposeClientAppleEventQueue (
  96.     AVTClientDataPtr            pAVTClientData);
  97.  
  98. static OSStatus    AVTAddDriver (
  99.     GDFDeviceEventDataPtr        pGDFDeviceEventData,
  100.     AVTDriverID                    *pAVTDriverID);
  101.  
  102. static OSStatus    CreateAVTDriverID (
  103.     AVTDriverID                    *pAVTDriverID);
  104.  
  105. static void    DisposeAVTDriver (
  106.     AVTDriverID                    avtDriverID);
  107.  
  108. static AVTDriverID    AVTFindDriver (
  109.     RegEntryIDPtr                pRegEntryID);
  110.  
  111.  
  112. ////////////////////////////////////////////////////////////////////////////////
  113. ////////////////////////////////////////////////////////////////////////////////
  114. //
  115. // Public routines.
  116. //
  117. ////////////////////////////////////////////////////////////////////////////////
  118. ////////////////////////////////////////////////////////////////////////////////
  119.  
  120. ////////////////////////////////////////////////////////////////////////////////
  121. //
  122. // RegisterAVTClientApplication
  123. //
  124. //   This routine registers the calling application as a client of the
  125. // AV transport control driver family.
  126. //
  127.  
  128. OSStatus    RegisterAVTClientApplication(
  129.     AVTClientID                    *pAVTClientID,
  130.     UInt32                        clientContextData)
  131. {
  132.     AVTClientID                    avtClientID = kInvalidAVTClientID;
  133.     AVTClientDataPtr            pAVTClientData = nil,
  134.                                 pNextAVTClientData;
  135.     ProcessSerialNumber            currentPSN;
  136.     OSStatus                    status = noErr;
  137.  
  138.     // Allocate client data record.
  139.     pAVTClientData =
  140.         (AVTClientDataPtr) PoolAllocateResident (sizeof (AVTClientData), true);
  141.     if (pAVTClientData != nil)
  142.     {
  143.         pAVTClientData->clientContextData = clientContextData;
  144.         avtClientID = (AVTClientID) pAVTClientData;
  145.     }
  146.     else
  147.     {
  148.         status = memFullErr;
  149.     }
  150.  
  151.     // Add client data record to list.
  152.     if (status == noErr)
  153.     {
  154.         pNextAVTClientData = gpAVTFamilyData->pAVTClientList;
  155.         if (pNextAVTClientData != nil)
  156.             pNextAVTClientData->pPrevAVTClientData = pAVTClientData;
  157.  
  158.         pAVTClientData->pPrevAVTClientData = nil;
  159.         pAVTClientData->pNextAVTClientData = pNextAVTClientData;
  160.         gpAVTFamilyData->pAVTClientList = pAVTClientData;
  161.     }
  162.  
  163.     // Create client Apple Event queue.
  164.     if (status == noErr)
  165.         status = AVTCreateClientAppleEventQueue (pAVTClientData);
  166.  
  167.     // Create an Apple Event target descriptor for the client.
  168.     if (status == noErr)
  169.     {
  170.         status = GetCurrentProcess (¤tPSN);
  171.  
  172.         if (status == noErr)
  173.         {
  174.             status = AECreateDesc (typeProcessSerialNumber,
  175.                                    ¤tPSN,
  176.                                    sizeof (ProcessSerialNumber),
  177.                                    &(pAVTClientData->clientAEAddress));
  178.             if (status == noErr)
  179.                 pAVTClientData->clientAEAddressValid = true;
  180.         }
  181.     }
  182.  
  183.     // Create an Apple Event for device added notification.
  184.     if (status == noErr)
  185.     {
  186.         status = AECreateAppleEvent
  187.                     (kAEAVTransportEventClass,
  188.                      kAEAVTransportDeviceAdded,
  189.                      &(pAVTClientData->clientAEAddress),
  190.                      kAutoGenerateReturnID,
  191.                      kAnyTransactionID,
  192.                      &(pAVTClientData->deviceAddedAppleEvent));
  193.         if (status == noErr)
  194.             pAVTClientData->deviceAddedAppleEventValid = true;
  195.     }
  196.  
  197.     // Create an Apple Event for device removed notification.
  198.     if (status == noErr)
  199.     {
  200.         status = AECreateAppleEvent
  201.                     (kAEAVTransportEventClass,
  202.                      kAEAVTransportDeviceRemoved,
  203.                      &(pAVTClientData->clientAEAddress),
  204.                      kAutoGenerateReturnID,
  205.                      kAnyTransactionID,
  206.                      &(pAVTClientData->deviceRemovedAppleEvent));
  207.         if (status == noErr)
  208.             pAVTClientData->deviceRemovedAppleEventValid = true;
  209.     }
  210.  
  211.     // Clean up on error.
  212.     if (status != noErr)
  213.     {
  214.         if (avtClientID != kInvalidAVTClientID)
  215.             UnregisterAVTClientApplication (avtClientID);
  216.     }
  217.  
  218.     // Return results.
  219.     *pAVTClientID = avtClientID;
  220.  
  221.     return (status);
  222. }
  223.  
  224.  
  225. ////////////////////////////////////////////////////////////////////////////////
  226. //
  227. // UnregisterAVTClientApplication
  228. //
  229. //   This routine unregisters the calling application as a client of the
  230. // AV transport control driver family.
  231. //
  232.  
  233. OSStatus    UnregisterAVTClientApplication(
  234.     AVTClientID                    avtClientID)
  235. {
  236.     AVTClientDataPtr            pAVTClientData,
  237.                                 pPrevAVTClientData,
  238.                                 pNextAVTClientData;
  239.     OSStatus                    status = noErr;
  240.  
  241.     if (avtClientID != kInvalidAVTClientID)
  242.     {
  243.         // Get client data from ID.
  244.         pAVTClientData = (AVTClientDataPtr) avtClientID;
  245.  
  246.         // Deallocate device removed Apple Event.
  247.         if (pAVTClientData->deviceRemovedAppleEventValid)
  248.             AEDisposeDesc (&(pAVTClientData->deviceRemovedAppleEvent));
  249.  
  250.         // Deallocate device added Apple Event.
  251.         if (pAVTClientData->deviceAddedAppleEventValid)
  252.             AEDisposeDesc (&(pAVTClientData->deviceAddedAppleEvent));
  253.  
  254.         // Deallocate target descriptor.
  255.         if (pAVTClientData->clientAEAddressValid)
  256.             AEDisposeDesc (&(pAVTClientData->clientAEAddress));
  257.  
  258.         // Dispose of client Apple Event queue.
  259.         if (pAVTClientData->clientAppleEventQueue != nil)
  260.             AVTDisposeClientAppleEventQueue (pAVTClientData);
  261.  
  262.         // Remove client from list.
  263.         pPrevAVTClientData = pAVTClientData->pPrevAVTClientData;
  264.         pNextAVTClientData = pAVTClientData->pNextAVTClientData;
  265.  
  266.         if (pPrevAVTClientData != nil)
  267.             pPrevAVTClientData->pNextAVTClientData = pNextAVTClientData;
  268.         else
  269.             gpAVTFamilyData->pAVTClientList = pNextAVTClientData;
  270.  
  271.         if (pNextAVTClientData != nil)
  272.             pNextAVTClientData->pPrevAVTClientData = pPrevAVTClientData;
  273.  
  274.         // Deallocate client data record.
  275.         PoolDeallocate ((Ptr) pAVTClientData);
  276.     }
  277.  
  278.     return (status);
  279. }
  280.  
  281.  
  282. ////////////////////////////////////////////////////////////////////////////////
  283. //
  284. // GetAVTDriverList
  285. //
  286. //   This routine returns a list of AV transport control driver IDs and the
  287. // number of drivers installed in the system.
  288. //
  289.  
  290. OSStatus    GetAVTDriverList(
  291.     AVTDriverID                    *pAVTDriverIDList,
  292.     UInt32                        avtDriverIDListSize,
  293.     UInt32                        *pNumAVTDrivers)
  294. {
  295.     AVTDriverDataPtr            pAVTDriverData;
  296.     UInt32                        numAVTDrivers,
  297.                                 numAVTDriversInList,
  298.                                 driverNum;
  299.     OSStatus                    status = noErr;
  300.  
  301.     // Compute number of drivers to put in list.
  302.     numAVTDrivers = gpAVTFamilyData->numAVTDrivers;
  303.     numAVTDriversInList = avtDriverIDListSize;
  304.     if (numAVTDriversInList > numAVTDrivers)
  305.         numAVTDriversInList = numAVTDrivers;
  306.  
  307.     // Copy driver IDs in order.
  308.     pAVTDriverData = gpAVTFamilyData->pAVTDriverList;
  309.     for (driverNum = 0; driverNum < numAVTDriversInList; driverNum++)
  310.     {
  311.         pAVTDriverIDList[driverNum] = (AVTDriverID) pAVTDriverData;
  312.         pAVTDriverData = pAVTDriverData->pNextAVTDriverData;
  313.     }
  314.  
  315.     // Return number of installed drivers.
  316.     *pNumAVTDrivers = numAVTDrivers;
  317.  
  318.     return (status);
  319. }
  320.  
  321.  
  322. ////////////////////////////////////////////////////////////////////////////////
  323. //
  324. // CallAVTDriver
  325. //
  326. //   This routine sends a request to the given driver.
  327. //
  328.  
  329. OSStatus    CallAVTDriver(
  330.     AVTDriverID                    avtDriverID,
  331.     AVTInterfaceParamsPtr        pAVTInterfaceParams)
  332. {
  333.     AVTDriverDataPtr            pAVTDriverData;
  334.     CntrlParam                    cntrlParam;
  335.     OSStatus                    status = noErr;
  336.  
  337.     // Get the driver data from the ID.
  338.     pAVTDriverData = (AVTDriverDataPtr) avtDriverID;
  339.  
  340. /*zzz*/
  341.     if (pAVTDriverData->deviceDisconnected)
  342.         return (-139);//zzz need disconnectedErr
  343. /*zzz*/
  344.     // Set up control parameters.
  345.     cntrlParam.ioCompletion = nil;
  346.     cntrlParam.ioVRefNum = 0;
  347.     cntrlParam.ioCRefNum = pAVTDriverData->driverRefNum;
  348.     cntrlParam.csCode = cscAVTCommand;
  349.     *((Ptr *) &(cntrlParam.csParam[0])) = (Ptr) pAVTInterfaceParams;
  350.  
  351.     // Call the driver.
  352.     status = PBControlSync ((ParmBlkPtr) &cntrlParam);
  353.  
  354.     return (status);
  355. }
  356.  
  357.  
  358. ////////////////////////////////////////////////////////////////////////////////
  359. //
  360. // OpenAVTDriver
  361. //
  362. //   This routine opens a connection to the given driver.
  363. //
  364.  
  365. OSStatus    OpenAVTDriver (
  366.     AVTDriverID                    avtDriverID)
  367. {
  368.     AVTDriverDataPtr            pAVTDriverData;
  369.     OSStatus                    status = noErr;
  370.  
  371.     // Get the driver data from the ID.
  372.     pAVTDriverData = (AVTDriverDataPtr) avtDriverID;
  373.  
  374.     // One more connection.
  375.     pAVTDriverData->numConnections++;
  376.  
  377.     return (status);
  378. }
  379.  
  380.  
  381. ////////////////////////////////////////////////////////////////////////////////
  382. //
  383. // CloseAVTDriver
  384. //
  385. //   This routine closes a connection to the given driver.
  386. //
  387.  
  388. OSStatus    CloseAVTDriver (
  389.     AVTDriverID                    avtDriverID)
  390. {
  391.     AVTDriverDataPtr            pAVTDriverData;
  392.     OSStatus                    status = noErr;
  393.  
  394.     // Get the driver data from the ID.
  395.     pAVTDriverData = (AVTDriverDataPtr) avtDriverID;
  396.  
  397.     // One less connection.
  398.     pAVTDriverData->numConnections--;
  399.  
  400.     // Dispose driver if device has been disconnected.
  401.     if ((pAVTDriverData->deviceDisconnected) && (pAVTDriverData->numConnections == 0))
  402.         DisposeAVTDriver (avtDriverID);
  403.  
  404.     return (status);
  405. }
  406.  
  407.  
  408. ////////////////////////////////////////////////////////////////////////////////
  409. //
  410. // GetNextAVTClientEvent
  411. //
  412. //   This routine checks if any client Apple Events are pending and sends any
  413. // that are.
  414. //
  415.  
  416. OSStatus    GetNextAVTClientEvent(
  417.     AVTClientID                    avtClientID)
  418. {
  419.     AVTClientDataPtr            pAVTClientData;
  420.     ClientAppleEventDataPtr        pClientAppleEventData;
  421.     AppleEvent                    reply;
  422.     OSStatus                    status = noErr,
  423.                                 queueStatus = noErr;
  424.  
  425.     // Get client data from ID.
  426.     pAVTClientData = (AVTClientDataPtr) avtClientID;
  427.  
  428.     // Send any client Apple Events on queue.
  429.     while (queueStatus == noErr)
  430.     {
  431.         queueStatus = PBDequeueFirst (pAVTClientData->clientAppleEventQueue,
  432.                                       (QElemPtr *) &pClientAppleEventData);
  433.         if (queueStatus == noErr)
  434.         {
  435.             // Send the Apple Event.
  436.             AESend (&(pClientAppleEventData->clientAppleEvent),
  437.                     &reply,
  438.                     pClientAppleEventData->sendMode,
  439.                     pClientAppleEventData->sendPriority,
  440.                     pClientAppleEventData->timeOutInTicks,
  441.                     pClientAppleEventData->idleProc,
  442.                     pClientAppleEventData->filterProc);
  443.  
  444.             // Dispose of reply.
  445.             AEDisposeDesc (&reply);
  446.  
  447.             // We're now done with the client Apple Event data record.
  448.             DisposeClientAppleEventData (pClientAppleEventData);
  449.         }
  450.     }
  451.  
  452.     return (status);
  453. }
  454.  
  455.  
  456. ////////////////////////////////////////////////////////////////////////////////
  457. ////////////////////////////////////////////////////////////////////////////////
  458. //
  459. // Private routines.
  460. //
  461. ////////////////////////////////////////////////////////////////////////////////
  462. ////////////////////////////////////////////////////////////////////////////////
  463.  
  464. ////////////////////////////////////////////////////////////////////////////////
  465. //
  466. // InitializeAVTFamily
  467. //
  468. //   This routine initializes the AV transport control driver family.
  469. //
  470.  
  471. long    InitializeAVTFamily(void)
  472. {
  473.     OSStatus                    status = noErr;
  474.  
  475.     // Allocate family global record.
  476.     gpAVTFamilyData =
  477.         (AVTFamilyDataPtr) PoolAllocateResident (sizeof (AVTFamilyData), true);
  478.     if (gpAVTFamilyData == nil)
  479.         status = memFullErr;
  480.  
  481.     return ((long) status);
  482. }
  483.  
  484.  
  485. ////////////////////////////////////////////////////////////////////////////////
  486. //
  487. // TerminateAVTFamily
  488. //
  489. //   This routine terminates the AV transport control driver family.
  490. //
  491.  
  492. long    TerminateAVTFamily(void)
  493. {
  494.     OSStatus                    status = noErr;
  495.  
  496.     // Deallocate family global record.
  497.     if (gpAVTFamilyData != nil)
  498.         PoolDeallocate ((Ptr) gpAVTFamilyData);
  499.  
  500.     return ((long) status);
  501. }
  502.  
  503.  
  504. ////////////////////////////////////////////////////////////////////////////////
  505. //
  506. // InstallAVTExpert
  507. //
  508. //   This routine installs the AV transport control driver expert loading
  509. // mechanism.
  510. //
  511.  
  512. OSStatus    InstallAVTExpert(void)
  513. {
  514.     UInt32                        eventTable[1];
  515.     OSStatus                    status = noErr;
  516.  
  517.     // Register to receive generic device added events.
  518.     eventTable[0] = kGDFDeviceAddedEvent;
  519.     eventTable[1] = kGDFDeviceRemovedEvent;
  520.     status = GDFRegisterDeviceEventHandlerProc
  521.                 (kNdrvTypeIsAVTransport,
  522.                  2,
  523.                  &eventTable[0],
  524.                  AVTEventHandler,
  525.                  nil,
  526.                  &(gpAVTExpertData->gdfDeviceEventRegistrationID));
  527.  
  528.     return (status);
  529. }
  530.  
  531.  
  532. ////////////////////////////////////////////////////////////////////////////////
  533. //
  534. // UninstallAVTExpert
  535. //
  536. //   This routine uninstalls the AV transport control driver expert loading
  537. // mechanism.
  538. //
  539.  
  540. OSStatus    UninstallAVTExpert(void)
  541. {
  542.     OSStatus                    status = noErr;
  543.  
  544.     // Dispose of AVTExpert data.
  545.     if (gpAVTExpertData != nil)
  546.     {
  547.         // Unregister with Generic Device family.
  548.         if (gpAVTExpertData->gdfDeviceEventRegistrationID !=
  549.             kInvalidGDFDeviceEventRegistrationID)
  550.         {
  551.             status = GDFUnregisterDeviceEventHandler
  552.                         (gpAVTExpertData->gdfDeviceEventRegistrationID);
  553.         }
  554.  
  555.         PoolDeallocate ((Ptr) gpAVTExpertData);
  556.         gpAVTExpertData = nil;
  557.     }
  558.  
  559.     return (status);
  560. }
  561.  
  562.  
  563. ////////////////////////////////////////////////////////////////////////////////
  564. ////////////////////////////////////////////////////////////////////////////////
  565. //
  566. // Internal routines.
  567. //
  568. ////////////////////////////////////////////////////////////////////////////////
  569. ////////////////////////////////////////////////////////////////////////////////
  570.  
  571. ////////////////////////////////////////////////////////////////////////////////
  572. //
  573. // AVTEventHandler
  574. //
  575. //   This proc handles device events for AV transport devices.
  576. //
  577.  
  578. static OSStatus    AVTEventHandler(
  579.     GDFDeviceEventDataPtr        pGDFDeviceEventData)
  580. {
  581.     OSStatus                    status = noErr;
  582.  
  583.     // Dispatch off of device event.
  584.     switch (pGDFDeviceEventData->deviceEvent)
  585.     {
  586.         case kGDFDeviceAddedEvent :
  587.             status = AVTHandleDeviceAdded (pGDFDeviceEventData);
  588.             break;
  589.  
  590.         case kGDFDeviceRemovedEvent :
  591.             status = AVTHandleDeviceRemoved (pGDFDeviceEventData);
  592.             break;
  593.  
  594.         default :
  595.             break;
  596.     }
  597.  
  598.     return (status);
  599. }
  600.  
  601.  
  602. ////////////////////////////////////////////////////////////////////////////////
  603. //
  604. // AVTHandleDeviceAdded
  605. //
  606. //   This routine handles new devices being added.
  607. //
  608.  
  609. static OSStatus    AVTHandleDeviceAdded(
  610.     GDFDeviceEventDataPtr        pGDFDeviceEventData)
  611. {
  612.     AVTDriverID                    avtDriverID;
  613.     AVTDriverDataPtr            pAVTDriverData;
  614.  
  615.     AVTClientDataPtr            pAVTClientData;
  616.  
  617.     OSStatus                    status = noErr,
  618.                                 clientStatus;
  619.  
  620.     // Check if avt driver is in our list.  This will happen if device was
  621.     // connected, opened, disconnected, and reconnected without being closed.
  622.     // If it's in our list, set disconnected to false.
  623.     avtDriverID = AVTFindDriver (&(pGDFDeviceEventData->deviceRegEntryID));
  624.     if (avtDriverID != kInvalidAVTDriverID)
  625.     {
  626.         pAVTDriverData = (AVTDriverDataPtr) avtDriverID;
  627.         pAVTDriverData->deviceDisconnected = false;
  628.     }
  629.     else
  630.     {
  631.         status = AVTAddDriver (pGDFDeviceEventData, &avtDriverID);
  632.         if (status == noErr)
  633.             pAVTDriverData = (AVTDriverDataPtr) avtDriverID;
  634.     }
  635.  
  636.     // Send up notification to all clients.
  637.     if (status == noErr)
  638.     {
  639.         pAVTClientData = gpAVTFamilyData->pAVTClientList;
  640.         while (pAVTClientData != nil)
  641.         {
  642.             // Add the driver ID parameter to event.
  643.             clientStatus = AEPutParamPtr
  644.                             (&(pAVTClientData->deviceAddedAppleEvent),
  645.                              kAEAVTDriverIDKey,
  646.                              kAEAVTDriverIDType,
  647.                              &avtDriverID,
  648.                              sizeof (AVTDriverID));
  649.  
  650.             // Send event.
  651.             if (clientStatus == noErr)
  652.             {
  653.                 clientStatus = AVTSendClientAppleEvent
  654.                                 (pAVTClientData,
  655.                                  &(pAVTClientData->deviceAddedAppleEvent),
  656.                                  0,
  657.                                  kAENormalPriority,
  658.                                  0,
  659.                                  nil,
  660.                                  nil);
  661.             }
  662.  
  663.             pAVTClientData = pAVTClientData->pNextAVTClientData;
  664.         }
  665.     }
  666.  
  667.     return (status);
  668. }
  669.  
  670.  
  671. ////////////////////////////////////////////////////////////////////////////////
  672. //
  673. // AVTHandleDeviceRemoved
  674. //
  675. //   This routine handles devices being removed.
  676. //
  677.  
  678. static OSStatus    AVTHandleDeviceRemoved(
  679.     GDFDeviceEventDataPtr        pGDFDeviceEventData)
  680. {
  681.     RegEntryIDPtr                pRegEntryID;
  682.     AVTDriverID                    avtDriverID;
  683.     AVTDriverDataPtr            pAVTDriverData;
  684.     AVTClientDataPtr            pAVTClientData;
  685.     Boolean                        found;
  686.     OSStatus                    status = noErr,
  687.                                 clientStatus;
  688.  
  689.     // Get Name Registry entry.
  690.     pRegEntryID = &(pGDFDeviceEventData->deviceRegEntryID);
  691.  
  692.     // Find driver that is being removed.
  693.     avtDriverID = AVTFindDriver (pRegEntryID);
  694.     if (avtDriverID != kInvalidAVTDriverID)
  695.     {
  696.         pAVTDriverData = (AVTDriverDataPtr) avtDriverID;
  697.         found = true;
  698.     }
  699.     else
  700.     {
  701.         found = false;
  702.     }
  703.  
  704.     // If driver was found, set it disconnected.
  705.     if (found)
  706.         pAVTDriverData->deviceDisconnected = true;
  707.  
  708.     // Dispose driver if no one has it open.
  709.     // Otherwise, send up notification to all clients.
  710.     if (found)
  711.     {
  712.         if (pAVTDriverData->numConnections == 0)
  713.         {
  714.             DisposeAVTDriver ((AVTDriverID) pAVTDriverData);
  715.         }
  716.         else
  717.         {
  718.             pAVTClientData = gpAVTFamilyData->pAVTClientList;
  719.             while (pAVTClientData != nil)
  720.             {
  721.                 // Add the driver ID parameter to event.
  722.                 clientStatus = AEPutParamPtr
  723.                                 (&(pAVTClientData->deviceRemovedAppleEvent),
  724.                                  kAEAVTDriverIDKey,
  725.                                  kAEAVTDriverIDType,
  726.                                  &avtDriverID,
  727.                                  sizeof (AVTDriverID));
  728.  
  729.                 // Send event.
  730.                 if (clientStatus == noErr)
  731.                 {
  732.                     clientStatus = AVTSendClientAppleEvent
  733.                                     (pAVTClientData,
  734.                                      &(pAVTClientData->deviceRemovedAppleEvent),
  735.                                      0,
  736.                                      kAENormalPriority,
  737.                                      0,
  738.                                      nil,
  739.                                      nil);
  740.                 }
  741.  
  742.                 pAVTClientData = pAVTClientData->pNextAVTClientData;
  743.             }
  744.         }
  745.     }
  746.  
  747.     return (status);
  748. }
  749.  
  750.  
  751. ////////////////////////////////////////////////////////////////////////////////
  752. //
  753. // AVTSendClientAppleEvent
  754. //
  755. //   This routine queues an Apple Event to be sent to a client for device
  756. // notification.
  757. //
  758.  
  759. static OSErr    AVTSendClientAppleEvent(
  760.     AVTClientDataPtr            pAVTClientData,
  761.     const AppleEvent            *theAppleEvent,
  762.     AESendMode                    sendMode,
  763.     AESendPriority                sendPriority,
  764.     long                        timeOutInTicks,
  765.     AEIdleUPP                    idleProc,
  766.     AEFilterUPP                    filterProc)
  767. {
  768.     ClientAppleEventDataPtr        pClientAppleEventData = nil;    
  769.     OSErr                        err = noErr;
  770.  
  771.     // Create data for the client Apple Event.
  772.     pClientAppleEventData = (ClientAppleEventDataPtr)
  773.         PoolAllocateResident (sizeof (ClientAppleEventData), true);
  774.     if (pClientAppleEventData != nil)
  775.     {
  776.         pClientAppleEventData->sendMode =
  777.             (sendMode & ~(kAENoReply | kAEQueueReply | kAEWaitReply)) | kAENoReply;
  778.         pClientAppleEventData->sendPriority = sendPriority;
  779.         pClientAppleEventData->timeOutInTicks = timeOutInTicks;
  780.         pClientAppleEventData->idleProc = idleProc;
  781.         pClientAppleEventData->filterProc = filterProc;
  782.     }
  783.     else
  784.     {
  785.         err = memFullErr;
  786.     }
  787.  
  788.     // Copy the given Apple Event.
  789.     if (err == noErr)
  790.     {
  791.         err = AEDuplicateDesc (theAppleEvent,
  792.                                &(pClientAppleEventData->clientAppleEvent));
  793.         if (err == noErr)
  794.             pClientAppleEventData->clientAppleEventValid = true;
  795.     }
  796.  
  797.     // Queue the client Apple Event to be sent at a good time.
  798.     if (err == noErr)
  799.     {
  800.         err = PBEnqueueLast ((QElemPtr) pClientAppleEventData,
  801.                              pAVTClientData->clientAppleEventQueue);
  802.     }
  803.  
  804.     // Clean up on error.
  805.     if (err != noErr)
  806.         DisposeClientAppleEventData (pClientAppleEventData);
  807.  
  808.     return (err);
  809. }
  810.  
  811.  
  812. ////////////////////////////////////////////////////////////////////////////////
  813. //
  814. // DisposeClientAppleEventData
  815. //
  816. //   This routine disposes of the client Apple Event record.
  817. //
  818.  
  819. static void    DisposeClientAppleEventData(
  820.     ClientAppleEventDataPtr        pClientAppleEventData)
  821. {
  822.     if (pClientAppleEventData != nil)
  823.     {
  824.         // Dispose of Apple Event copy.
  825.         if (pClientAppleEventData->clientAppleEventValid)
  826.             AEDisposeDesc (&(pClientAppleEventData->clientAppleEvent));
  827.  
  828.         // Dispose of client Apple Event data record.
  829.         PoolDeallocate ((Ptr) pClientAppleEventData);
  830.     }
  831. }
  832.  
  833.  
  834. ////////////////////////////////////////////////////////////////////////////////
  835. //
  836. // AVTCreateClientAppleEventQueue
  837. //
  838. //   This routine creates a client AppleEvent queue.
  839. //
  840.  
  841. static OSStatus    AVTCreateClientAppleEventQueue(
  842.     AVTClientDataPtr            pAVTClientData)
  843. {
  844.     OSStatus                    status = noErr;
  845.  
  846.     status = PBQueueCreate (&(pAVTClientData->clientAppleEventQueue));
  847.  
  848.     return (status);
  849. }
  850.  
  851.  
  852. ////////////////////////////////////////////////////////////////////////////////
  853. //
  854. // AVTDisposeClientAppleEventQueue
  855. //
  856. //   This routine disposes of a client AppleEvent queue.
  857. //
  858.  
  859. static OSStatus    AVTDisposeClientAppleEventQueue(
  860.     AVTClientDataPtr            pAVTClientData)
  861. {
  862.     ClientAppleEventDataPtr        pClientAppleEventData;
  863.     OSStatus                    status = noErr;
  864.  
  865.     if (pAVTClientData->clientAppleEventQueue != nil)
  866.     {
  867.         // Dispose of any client AppleEvents still in queue.
  868.         while (status == noErr)
  869.         {
  870.             status = PBDequeueFirst (pAVTClientData->clientAppleEventQueue,
  871.                                      (QElemPtr *) &pClientAppleEventData);
  872.             if (status == noErr)
  873.                 DisposeClientAppleEventData (pClientAppleEventData);
  874.         }
  875.  
  876.         // Delete queue.
  877.         PBQueueDelete (pAVTClientData->clientAppleEventQueue);
  878.     }
  879.  
  880.     return (status);
  881. }
  882.  
  883.  
  884. ////////////////////////////////////////////////////////////////////////////////
  885. //
  886. // AVTAddDriver
  887. //
  888. //   This routine adds a new driver.
  889. //
  890.  
  891. static OSStatus    AVTAddDriver(
  892.     GDFDeviceEventDataPtr        pGDFDeviceEventData,
  893.     AVTDriverID                    *pAVTDriverID)
  894. {
  895.     RegEntryIDPtr                pRegEntryID;
  896.     AVTDriverID                    avtDriverID = kInvalidAVTDriverID;
  897.     AVTDriverDataPtr            pAVTDriverData;
  898.  
  899.     OSStatus                    status = noErr;
  900.  
  901.     // Get Name Registry entry.
  902.     pRegEntryID = &(pGDFDeviceEventData->deviceRegEntryID);
  903.  
  904.     // Add AV transport control driver record to list.
  905.     if (status == noErr)
  906.         status = CreateAVTDriverID (&avtDriverID);
  907.  
  908.     // Get the driver data from the ID.
  909.     if (status == noErr)
  910.         pAVTDriverData = (AVTDriverDataPtr) avtDriverID;
  911.  
  912.     // Fill in driver data record.
  913.     if (status == noErr)
  914.     {
  915.         pAVTDriverData->deviceRegistryID = *pRegEntryID;
  916.         pAVTDriverData->driverRefNum = pGDFDeviceEventData->driverRefNum;
  917.     }
  918.  
  919.     // Open driver.
  920.     if (status == noErr)
  921.     {
  922.         status = OpenInstalledDriver (pGDFDeviceEventData->driverRefNum, fsRdWrPerm);
  923.         if (status == noErr)
  924.             pAVTDriverData->driverOpened = true;
  925.     }
  926.  
  927.     // Clean up on error.
  928.     if (status != noErr)
  929.     {
  930.         if (avtDriverID != kInvalidAVTDriverID)
  931.             DisposeAVTDriver (avtDriverID);
  932.     }
  933.  
  934.     // Return results.
  935.     if (status == noErr)
  936.         *pAVTDriverID = avtDriverID;
  937.     else
  938.         *pAVTDriverID = kInvalidAVTDriverID;
  939.  
  940.     return (status);
  941. }
  942.  
  943.  
  944. ////////////////////////////////////////////////////////////////////////////////
  945. //
  946. // CreateAVTDriverID
  947. //
  948. //   This routine creates a new AV transport control driver record, adds it to
  949. // the family list, and returns the ID for the new driver record.
  950. //
  951.  
  952. static OSStatus    CreateAVTDriverID(
  953.     AVTDriverID                    *pAVTDriverID)
  954. {
  955.     AVTDriverDataPtr            pAVTDriverData = nil,
  956.                                 pNextAVTDriverData;
  957.     OSStatus                    status = noErr;
  958.  
  959.     // Allocate AV transport control driver record.
  960.     pAVTDriverData = (AVTDriverDataPtr)
  961.         PoolAllocateResident (sizeof (AVTDriverData), true);
  962.     if (pAVTDriverData != nil)
  963.         pAVTDriverData->avtDriverID = (AVTDriverID) pAVTDriverData;
  964.     else
  965.         status = memFullErr;
  966.  
  967.     // Add driver record to family list.
  968.     if (status == noErr)
  969.     {
  970.         pNextAVTDriverData = gpAVTFamilyData->pAVTDriverList;
  971.         pAVTDriverData->pNextAVTDriverData = pNextAVTDriverData;
  972.         gpAVTFamilyData->pAVTDriverList = pAVTDriverData;
  973.         gpAVTFamilyData->numAVTDrivers++;
  974.     }
  975.  
  976.     // Return result and clean up on error.
  977.     if (status == noErr)
  978.     {
  979.         *pAVTDriverID = pAVTDriverData->avtDriverID;
  980.     }
  981.     else
  982.     {
  983.         if (pAVTDriverData != nil)
  984.             PoolDeallocate ((Ptr) pAVTDriverData);
  985.  
  986.         *pAVTDriverID = kInvalidAVTDriverID;
  987.     }
  988.  
  989.     return (status);
  990. }
  991.  
  992.  
  993. ////////////////////////////////////////////////////////////////////////////////
  994. //
  995. // DisposeAVTDriver
  996. //
  997. //   This routine disposes of the given driver.  It will call the driver to
  998. // terminate itself, dispose of the driver memory closure, remove the driver
  999. // data record from our list, and dispose of the driver data record.
  1000. //
  1001.  
  1002. static void    DisposeAVTDriver(
  1003.     AVTDriverID                    avtDriverID)
  1004. {
  1005.     AVTDriverDataPtr            pAVTDriverData,
  1006.                                 pSearchAVTDriverData,
  1007.                                 pPrevAVTDriverData;
  1008.     THz                            currentZone;
  1009.  
  1010.     // Switch to system zone.
  1011.     currentZone = GetZone ();
  1012.     SetZone (SystemZone ());
  1013.  
  1014.     // Get the driver data from the ID.
  1015.     pAVTDriverData = (AVTDriverDataPtr) avtDriverID;
  1016.  
  1017.     // Close the driver.
  1018.     if (pAVTDriverData->driverOpened)
  1019.         CloseDriver (pAVTDriverData->driverRefNum);
  1020.  
  1021.     // Remove driver record from family list.
  1022.     pSearchAVTDriverData = gpAVTFamilyData->pAVTDriverList;
  1023.     pPrevAVTDriverData = nil;
  1024.     while ((pSearchAVTDriverData != nil) &&
  1025.            (pSearchAVTDriverData != pAVTDriverData))
  1026.     {
  1027.         pPrevAVTDriverData = pSearchAVTDriverData;
  1028.         pSearchAVTDriverData =
  1029.             pSearchAVTDriverData->pNextAVTDriverData;
  1030.     }
  1031.     if (pSearchAVTDriverData != nil)
  1032.     {
  1033.         if (pPrevAVTDriverData != nil)
  1034.         {
  1035.             pPrevAVTDriverData->pNextAVTDriverData =
  1036.                 pAVTDriverData->pNextAVTDriverData;
  1037.         }
  1038.         else
  1039.         {
  1040.             gpAVTFamilyData->pAVTDriverList =
  1041.                 pAVTDriverData->pNextAVTDriverData;
  1042.         }
  1043.     }
  1044.     gpAVTFamilyData->numAVTDrivers--;
  1045.  
  1046.     // Deallocate driver data record.
  1047.     PoolDeallocate ((Ptr) pAVTDriverData);
  1048.  
  1049.     // Switch zone back.
  1050.     SetZone (currentZone);
  1051. }
  1052.  
  1053.  
  1054. ////////////////////////////////////////////////////////////////////////////////
  1055. //
  1056. // AVTFindDriver
  1057. //
  1058. //   This routine finds the AVT driver corresponding to the given Name Registry
  1059. // entry.
  1060. //
  1061.  
  1062. static AVTDriverID    AVTFindDriver(
  1063.     RegEntryIDPtr                pRegEntryID)
  1064. {
  1065.     AVTDriverID                    avtDriverID;
  1066.     AVTDriverDataPtr            pAVTDriverData;
  1067.     Boolean                        found;
  1068.  
  1069.     // Find driver that has matching name registry entry.
  1070.     pAVTDriverData = gpAVTFamilyData->pAVTDriverList;
  1071.     found = false;
  1072.     while ((pAVTDriverData != nil) && (!found))
  1073.     {
  1074.         if (RegistryEntryIDCompare (&(pAVTDriverData->deviceRegistryID), pRegEntryID))
  1075.             found = true;
  1076.         else
  1077.             pAVTDriverData = pAVTDriverData->pNextAVTDriverData;
  1078.     }
  1079.  
  1080.     // Set return value.
  1081.     if (found)
  1082.         avtDriverID = (AVTDriverID) pAVTDriverData;
  1083.     else
  1084.         avtDriverID = kInvalidAVTDriverID;
  1085.  
  1086.     return (avtDriverID);
  1087. }
  1088.